( function() {
	var element = Z.element;
	var Box = element.Box;
	var Label = element.Label;
	var Menu = Z.Menu;

	// 遍历链表
	function loopLinkList( root, func, last ) {
		var cur;
		last = last === undefined ? null : last;
		for ( cur = root; cur !== last; cur = cur.next ) {
			func( cur );
		}
	};

	// region 数据结构
	// 框架类型,共有三种框架类型,Window框架容纳具体的窗口,不能容纳框架
	// Row框架和Col框架是两个框架容器,用于容纳其他框架,框架容器不能容纳一般窗口
	var FrameType = {
		Window : 0,
		Row : 1,
		Col : 2
	};

	function gcd( a, b ) {
		var r;
		while ( b > 0 ) {
			r = a % b;
			a = b;
			b = r;
		}
		return a;
	}

	// 比例
	function Ratio( up, down ) {
		var g = gcd( up, down );
		return {
			up : up / g,
			down : down / g
		};
	}

	// 有理数乘法
	function mulRatio( lhs, rhs ) {
		var up = lhs.up * rhs.up;
		var down = lhs.down * rhs.down;
		var g = gcd( up, down );

		return Ratio( up / g, down / g );
	}

	// 框架容器模板,包括列容器和行容器
	function FrameContainer( type ) {
		return function( up, down ) {
			return {
				type : type,
				idealRatio : Ratio( up, down ),
				next : null,
				firstChild : null
			};
		};
	}

	// 窗口框架
	function WindowFrame( up, down ) {
		return {
			type : FrameType.Window,
			idealRatio : Ratio( up, down ),
			next : null
		};
	};

	var ColFrame = FrameContainer( FrameType.Col ); // 列容器
	var RowFrame = FrameContainer( FrameType.Row ); // 行容器
	// endregion

	// region 常量
	var FrameMargin = 4;
	var FrameTitleHeight = 22;
	var MinWindowLength = 10;
	var MinFrameLength = MinWindowLength + FrameMargin * 2 + 2;
	// endregion

	function drawFrameSystem( parentArea, root, body ) {
		var dRoot = DisplayNode( root );
		var curFocusFrame = null; // 焦点

		function focusFrame( dNode ) {
			if ( curFocusFrame !== null ) {
				curFocusFrame.unfocus();
			}
			dNode.focus();
			curFocusFrame = dNode;
		}

		function DisplayNode( node ) {
			if ( node.type === FrameType.Window ) {
				return {
					type : node.type,
					next : node.next,
					idealRatio : node.idealRatio,
					previous : null,
					parent : null,
					xBounds : null,
					yBounds : null,
					spacer : null,
					focus : null,
					unfocus : null,
					left : 0,
					top : 0,
					height : 0,
					width : 0
				};
			}
			else {
				return {
					type : node.type,
					next : node.next,
					firstChild : null,
					idealRatio : node.idealRatio,
					previous : null,
					parent : null,
					xBounds : null,
					yBounds : null,
					left : 0,
					top : 0,
					height : 0,
					width : 0,
					spacer : null,
					adjustRatio : null
				};
			}
		}

		// 对于一个布局容器来说,它只在一个方向上进行布局,于是有一个主维度和副维度
		// 行容器(Row)的主维度是x轴,也就是left/width,副维度是y轴,也就是top/height
		// 列容器(Col)的主维度是y轴,也就是top/height,副维度是x轴,也就是left/width
		function RowCol( type ) {
			return function( row, col ) {
				return type == FrameType.Row ? row : col;
			};
		}

		// 一个节点的四个位置尺寸属性
		function NodeAttr( attrName ) {
			return function( node, val ) {
				if ( val === undefined ) {
					return node[attrName];
				}
				else {
					node[attrName] = val;
				}
			};
		}
		var leftAttr = NodeAttr( "left" );
		var topAttr = NodeAttr( "top" );
		var widthAttr = NodeAttr( "width" );
		var heightAttr = NodeAttr( "height" );

		// 设置一个节点的xBounds和yBounds
		function xBounds( node, offset, length ) {
			return node.xBounds( offset, length );
		}

		function yBounds( node, offset, length ) {
			return node.yBounds( offset, length );
		}

		function layFrameSystemA( dRoot, firstChild ) {
			function layWindowFrame( dNode ) {
				var area = parentArea.area( {
							onMousedown : function() {
								focusFrame( dNode );
							}
						} ); // 区域

				var titleBar = Box( area, {
							background_color : "#EEEEEE",
							border_radius : "7px 7px 0px 0px",
							height : FrameTitleHeight
						} );
				var backgroundBox = Box( area, {
							top : FrameTitleHeight,
							background_color : "white",
							border_radius : "0px 0px 7px 7px"
						} ); // 背景
				var contentArea = area.area();

				dNode.xBounds = function( left, width ) {
					width = Math.max( FrameMargin * 2 + 2 + MinWindowLength, width );

					area.left( left + FrameMargin );

					var realWidth = width - 2 - FrameMargin * 2; // 实际的宽,减去了边框和空白

					area.width( realWidth );
					titleBar.width( realWidth );
					backgroundBox.width( realWidth );
					contentArea.width( realWidth );

					dNode.left = left;
					dNode.width = width;

					return width;
				};

				dNode.yBounds = function( top, height ) {
					height = Math.max( FrameMargin * 2 + 2 + MinWindowLength, height );

					area.top( top + FrameMargin );
					var realHeight = height - 2 - FrameMargin * 2; // 实际的高,减去了边框和空白

					area.height( realHeight );
					backgroundBox.height( realHeight - FrameTitleHeight );
					contentArea.height( realHeight - FrameTitleHeight );

					dNode.top = top;
					dNode.height = height;

					return height;
				};

				dNode.focus = function() {
					titleBar.background_color( "#CEDDED" );
				};
				dNode.unfocus = function() {
					titleBar.background_color( "#EEEEEE" );
				};
			};

			function layContainer( dNode ) {
				// 一个节点的四个另外一个维度的尺寸只读属性
				var RC = RowCol( dNode.type );
				var mainLength = RC( widthAttr, heightAttr );
				var subLength = RC( heightAttr, widthAttr );
				var mainOffset = RC( leftAttr, topAttr );
				var subOffset = RC( topAttr, leftAttr );

				// 设置子元素的bounds
				var childMainBounds = RC( xBounds, yBounds );
				var childSubBounds = RC( yBounds, xBounds );

				function mainBounds( offset, length ) {
					var curLength = 0; // 截止到目前的主长度
					var remindLength = length; // 剩余的长度,避免溢出

					// 遍历链表进行设置
					loopLinkList( dNode.firstChild, function( dNode ) {
								var thisLength = Math.min( Math.floor( dNode.idealRatio.up * length / dNode.idealRatio.down ), remindLength ); // 尺寸的计算值
								var realLength = childMainBounds( dNode, offset + curLength, thisLength ); // 布局,并获取实际的长度
								if ( dNode.spacer !== null ) {
									dNode.spacer.mainOffset( offset + curLength );
								}
								curLength += realLength;
								remindLength -= realLength;
							} );

					// 设置节点属性
					mainOffset( dNode, offset );
					mainLength( dNode, curLength );

					return curLength;
				}

				function subBounds( offset, length ) {
					var maxLength = length;
					var lastOverflow = null; // 最后一个溢出的子节点

					// 使用length对子节点进行设置,如果有子节点实际长度大于length,记录之
					loopLinkList( dNode.firstChild, function( dNode ) {
								var length = childSubBounds( dNode, offset, maxLength );
								if ( dNode.spacer !== null ) {
									dNode.spacer.subBounds( offset, maxLength );
								}

								// 如果某个节点长度超过了最长长度,记录该节点,更改最长长度
								if ( length > maxLength ) {
									lastOverflow = dNode;
									maxLength = length;
								}
							} );

					// 如果存在溢出的子节点,重新设置之前子节点的长度
					loopLinkList( dNode.firstChild, function( dNode ) {
								childSubBounds( dNode, offset, maxLength );
								if ( dNode.spacer !== null ) {
									dNode.spacer.subBounds( offset, maxLength );
								}

							}, lastOverflow );

					// 设置节点属性
					subOffset( dNode, offset );
					subLength( dNode, maxLength );

					return maxLength;
				}

				if ( dNode.type === FrameType.Row ) {
					dNode.xBounds = mainBounds;
					dNode.yBounds = subBounds;
				}
				else {
					dNode.xBounds = subBounds;
					dNode.yBounds = mainBounds;
				}

				dNode.adjustRatio = function() {
					// 使用当前的位置和尺寸重新调整比例
					var totalMainLength = mainLength( dNode );
					loopLinkList( dNode.firstChild, function( dNode ) {
								dNode.idealRatio = Ratio( mainLength( dNode ), totalMainLength );
							} );
				};
			}

			function laySpacer( dNode ) {
				// 一个节点的四个另外一个维度的尺寸只读属性
				var RC = RowCol( dNode.parent.type );
				var mainLength = RC( widthAttr, heightAttr );
				var mainOffset = RC( leftAttr, topAttr );

				// 设置子元素的bounds
				var childMainBounds = RC( xBounds, yBounds );

				// 分隔符分为行分隔符和列分隔符,但对外只有长度,主偏移和副偏移之说
				// 宽度总是固定的
				var cursor = RC( "e-resize", "n-resize" );

				var spacer = Box( parentArea, {
							zIndex : 1,
							cursor : cursor
						} ); // 分隔符控件

				var width = RC( spacer.width, spacer.height ); // 设置分隔符的宽度
				var mainOffsetA = RC( spacer.left, spacer.top ); // 设置分隔符的主偏移(但是需要考虑分隔符的宽度)
				var length = RC( spacer.height, spacer.width ); // 设置分隔符的长度
				var subOffset = RC( spacer.top, spacer.left ); // 设置分隔符的副偏移

				// 获取鼠标相对于parentArea的位置
				var getPos = RC( function( event ) {
							return event.clientX - parentArea.documentLeft();
						}, function( event ) {
							return event.clientY - parentArea.documentTop();
						} );
				width( FrameMargin * 2 ); // 设置宽度

				spacer.onMousedown( function( event ) {
							body.cursor( cursor ); // 设置全局的cursor
							event.preventDefault(); // 阻止选中事件触发
							dNode.parent.adjustRatio(); // 重新调整父容器框架比例

							var parentLength = mainLength( dNode.parent ); // 获取父容器框架的长度
							var start = mainOffset( dNode.previous ); // 前一个窗口的起始坐标
							var end = mainOffset( dNode ) + mainLength( dNode ); // 后一个窗口的结束坐标
							var length2 = end - start; // 两个窗口总计长度

							event.onMousemove( function( event ) {
										var pos = getPos( event ); // 鼠标的位置(相对于parentArea)
										var thisLen; // 其中一个框架的宽度
										if ( pos > mainOffset( dNode ) ) {
											thisLen = childMainBounds( dNode, Math.min( pos, end - MinFrameLength ), end - pos );
											if ( end - pos < thisLen ) {
												childMainBounds( dNode, end - thisLen, thisLen );
											}
											dNode.idealRatio = Ratio( thisLen, parentLength );
											childMainBounds( dNode.previous, start, length2 - thisLen );
											dNode.spacer.mainOffset( end - thisLen );
											dNode.previous.idealRatio = Ratio( length2 - thisLen, parentLength );
										}
										else {
											thisLen = childMainBounds( dNode.previous, start, pos - start );
											childMainBounds( dNode, start + thisLen, length2 - thisLen );
											dNode.spacer.mainOffset( start + thisLen );
											dNode.idealRatio = Ratio( length2 - thisLen, parentLength );
											dNode.previous.idealRatio = Ratio( thisLen, parentLength );
										}
									} );

							event.onMouseup( function( event ) {
										body.cursor( "default" );
									} );
						} );

				return {
					mainOffset : function( val ) {
						mainOffsetA( val - FrameMargin );
					},
					subBounds : function( offset, len ) {
						subOffset( offset );
						length( len );
					},
					remove : spacer.remove
				};
			}

			if ( dRoot.type === FrameType.Window ) {
				// 创建窗口框架控件
				layWindowFrame( dRoot );
			}
			else {
				// 创建容器框架
				layContainer( dRoot );

				// 遍历子节点,构建树,并创建控件
				var previousDNode = null;
				loopLinkList( firstChild, function( node ) {
							var dNode = DisplayNode( node );
							dNode.parent = dRoot;
							dNode.previous = previousDNode;

							// 如果不是第一个节点,置前一个节点的next节点为该节点,并放置分隔符
							// 否则置父节点的firstChild节点
							if ( previousDNode !== null ) {
								previousDNode.next = dNode;
								dNode.spacer = laySpacer( dNode );
							}
							else {
								dRoot.firstChild = dNode;
							}

							previousDNode = dNode;

							layFrameSystemA( dNode, node.type === FrameType.Window ? null : node.firstChild );
						} );
			}
		}

		layFrameSystemA( dRoot, root.type === FrameType.Window ? null : root.firstChild );

		// 链表后插
		function insertAfter( srcNode, targetNode ) {
			targetNode.parent = srcNode.parent;
			targetNode.next = srcNode.next;
			targetNode.previous = srcNode;
			srcNode.next = targetNode;
		}

		// 链表前插
		function insertBefore( srcNode, targetNode ) {
			targetNode.parent = srcNode.parent;
			targetNode.previous = srcNode.previous;
			targetNode.next = srcNode;
			srcNode.previous = targetNode;
		}

		// 置一个节点为另一个节点的父节点
		function beParent( srcNode, parentNode ) {
			srcNode.parent = parentNode;
			parentNode.firstChild = srcNode;

			parentNode.previous = srcNode.previous;
			if ( scrNode.previous !== null ) {
				srcNode.previous.next = parentNode;
			}

			parentNode.next = srcNode.next;
			if ( srcNode.next !== null ) {
				srcNode.next.previous = parentNode;
			}
		}

		function Insertion( frameType, insertAction ) {
			var RC = RowCol( FrameType );
			var mainLength = RC( widthAttr, heightAttr );
			var mainBounds = RC( xBounds, yBounds );
			var subBounds = RC( yBounds, xBounds );
			var CreateFrameNode = RC( RowFrame, ColFrame );

			return function( srcNode, targetNode ) {
				var parentNode = scrNode.parent;
				srcNode.parent.adjustRatio();

				// 无父节点
				if ( parentNode === null ) {
					parentNode = DisplayNode( CreateFrameNode( srcNode.idealRatio.up, srcNode.idealRatio.down ) );
					beParent( srcNode, parentNode );
					layContainer( parentNode );
				}
				// 父节点类型不对
				else if ( parentNode.type !== frameType ) {
					parentNode = DisplayNode( CreateFrameNode( srcNode.idealRatio.up, srcNode.idealRatio.down ) );
					parentNode.parent = srcNode.parent;

					// 如果源节点没有前节点,说明该节点是其父节点的firstChild,需要重新设置
					if ( srcNode.previous === null ) {
						srcNode.parent.firstChild = parentNode;
					}
					beParent( srcNode, parentNode );
				}

				// 父框架重新调整比例
				var oldMainLength = mainLength( srcNode ); // 原长度
				var newLeftLength = oldMainLength / 2; // 新长度
				var parentLength = mainLength( parentNode ); // 父长度

				// 计算出两个节点的新比例
				srcNode.idealRatio = Ratio( newLeftLength, parentLength );
				targetNode.idealRatio = Ratio( oldMainLength - newLeftLength, parentLength );

				// 执行插入操作
				insertAction( srcNode, targetNode );

				// 重新调整尺寸和位置
				mainBounds( srcNode.parent, parentNode.left, parentLength );
				subBounds( srcNode.parent, parentNode.top, parentNode.height );
			};
		}

		// 四个方向的插入
		var insertLeft = Insertion( FrameType.Row, insertBefore );
		var insertRight = Insertion( FrameType.Row, insertAfter );
		var insertTop = Insertion( FrameType.Col, insertBefore );
		var insertBottom = Insertion( FrameType.Col, insertAfter );

		// 测试一个节点能否分裂,满足条件是其主长度必须两个最小长度
		function CanSplit( frameType ) {
			var RC = RowCol( FrameType );
			var mainLength = RC( widthAttr, heightAttr );

			return function( dNode ) {
				return mainLength( dNode ) >= 2 * MinFrameLength;
			};
		}

		var canSplitRow = CanSplit( FrameType.Row );
		var canSplitCol = CanSplit( FrameType.Col );

		function nodeCurrying( func, node ) {
			return function( arg ) {
				return func( node, arg );
			};
		}

		return {
			xBounds : function( left, width ) {
				dRoot.xBounds( left, width );
			},
			yBounds : function( top, height ) {
				dRoot.yBounds( top, height );
			},
			focusFrame : function() {
				function focusCurrying( func ) {
					return nodeCurrying( func, curFocusFrame );
				};

				// 返回当前的焦点框架
				return curFocusFrame === null ? null : {
					canSplitRow : focusCurrying( canSplitRow ),
					canSplitCol : focusCurrying( canSplitCol ),
					insertLeft : focusCurrying( insertLeft ),
					insertRight : focusCurrying( insertRight ),
					insertTop : focusCurrying( insertTop ),
					insertBottom : focusCurrying( insertBottom )
				};
			}
		};
	}

	// 制作一个框架系统树,测试用
	function FrameSystem( setRoot ) {
		function FrameSystemA( previous, parentType, setNext ) {
			// previous是前一个节点给本节点的操作指令,用于是指前一个节点的next

			var thisNode = WindowFrame( 1, 1 ); // 当前节点
			var next = null; // 下一个节点(指令集)
			var parent = null; // 父节点

			var newParent = null; // 新父节点,临时变量

			previous.next( thisNode ); // 将前一个节点的下一个节点指向自己

			// 新节点创建时,将前一个节点的next设为自己,用于前一个节点通知本节点修改previous
			if ( setNext !== null ) {
				setNext( {
							previous : function( node ) {
								previous = node;
							}
						} );
			}

			function Split( type ) {
				var otherType = type === FrameType.Col ? FrameType.Row : FrameType.Col;
				var ContainerFrame = type === FrameType.Col ? ColFrame : RowFrame;

				return function( left, right ) {
					var total = left + right;
					var retVal = null;

					// 分割成两个窗口,计算各自的比例
					function split2() {
						var oldRatio = thisNode.idealRatio; // 先前的比例,该比例会被分裂
						var oldNext = thisNode.next; // 原先的下一个

						retVal = FrameSystemA( {
									next : function( node ) {
										thisNode.next = node;
									}
								}, parentType, function( setter ) {
									next = setter;
								} );

						thisNode.idealRatio = mulRatio( oldRatio, Ratio( left, total ) );
						thisNode.next.idealRatio = mulRatio( oldRatio, Ratio( right, total ) );
						thisNode.next.next = oldNext;
					}

					if ( parentType === null ) {
						// 如果没有父容器,生成一个父容器作为容器
						newParent = ContainerFrame();
						parent = newParent;
						parentType = type;
						parent.idealRatio = thisNode.idealRatio;
						parent.firstChild = thisNode;
						parent.next = thisNode.next;
						thisNode.next = null;
						thisNode.idealRatio = Ratio( 1, 1 );
						split2();
						if ( next !== null ) {
							next.previous( {
										next : function( node ) {
											newParent.next = node;
										}
									} );
						}
						previous.next( parent );
					}
					else if ( parentType === otherType ) {
						// 如果有父容器,但类型不对,生成一个新容器作为元父容器的子
						newParent = ContainerFrame();
						parentType = type;
						newParent.idealRatio = thisNode.idealRatio;
						if ( next !== null ) {
							next.previous( {
										next : function( node ) {
											newParent.next = node;
										}
									} );
						}
						if ( parent !== null ) {
							parent.firstChild = newParent;
						}
						else {
							previous.next( newParent );
						}

						newParent.firstChild = thisNode;
						thisNode.idealRatio = Ratio( 1, 1 );
						newParent.next = thisNode.next;
						thisNode.next = null;
						split2();
						parent = newParent;
					}
					else if ( parentType === type ) {
						// 否则分成两半
						split2();
					}

					return retVal;
				};
			}

			return {
				splitInRow : Split( FrameType.Row ),
				splitInCol : Split( FrameType.Col )
			};
		}

		return FrameSystemA( {
					next : setRoot
				}, null, null );
	}

	// region 菜单util
	var KeyCode = Z.Key.KeyCode;

	// 菜单类型
	var MenuType = {
		SubMenu : 1,
		Action : 2
	};

	// 注册只触发一次的事件
	function eventOnce( eventRegister, func ) {
		var thisEvent = null;
		thisEvent = eventRegister( function( event ) {
					func( event );
					thisEvent.remove();
				} );
	}

	// 子菜单节点
	function SubMenuNode( name, accessKey ) {
		return {
			type : MenuType.SubMenu,
			next : null,
			firstChild : null,
			name : name,
			accessKey : accessKey
		};
	}

	// 动作节点
	function ActionNode( name, action, verify, accessKey ) {
		return {
			type : MenuType.Action,
			next : null,
			action : action,
			name : name,
			accessKey : accessKey
		};
	}

	// 根据一个指针制作一个菜单
	function Menu( setRoot ) {
		var tail = null;

		function setTail( node ) {
			if ( tail === null ) {
				tail = node;
				setRoot( tail );
			}
			else {
				tail.next = node;
				tail = node;
			}
		};

		return {
			addSubMenu : function( name, accessKey ) {
				var subMenuNode = SubMenuNode( name, accessKey );
				setTail( subMenuNode );
				return Menu( function( node ) {
							subMenuNode.firstChild = node;
						} );
			},
			addAction : function( name, action, accessKey ) {
				setTail( ActionNode( name, action, accessKey ) );
			}
		};
	}

	function bannerMenuItem( name, menu, accessKey ) {
		return {
			name : name,
			menu : menu,
			accessKey : accessKey
		};
	}
	// endregion

	onLoad( function( body ) {
				var frameSystemRoot = null;

				// 创建一颗框架系统树
				var wind = FrameSystem( function( node ) {
							frameSystemRoot = node;
						} );
				var wind1 = wind.splitInRow( 1, 1 );
				wind.splitInCol( 3, 2 );
				var wind2 = wind1.splitInCol( 10, 11 );
				var wind3 = wind2.splitInRow( 3, 4 );
				wind3.splitInCol( 4, 5 );
				wind.splitInCol( 5, 6 );
				wind.splitInRow( 4, 9 );

				// 背景区域
				var ApplicationArea = body.area();
				var backgroundBox = Box( ApplicationArea, {
							background_color : "#E1E6F6"
						} );

				body.overflowX( "hidden" );
				body.overflowY( "hidden" );

				var frameSystem = drawFrameSystem( ApplicationArea, frameSystemRoot, body );

				var platform = {
					focusFrame : frameSystem.focusFrame
				};

				function CanSplit( canFunc ) {
					return function( platform ) {
						var frame = platform.focusFrame();
						return frame === null ? false : frame[canFunc];
					};
				}

				function DoInsert( insertFunc ) {
					return function( platform ) {
						var frame = platform.focusFrame();
						if ( frame !== null ) {
							frame[insertFunc]();
						}
					};
				}

				var canSplitRow = CanSplit( "canSplitRow" );
				var canSplitCol = CanSplit( "canSplitCol" );

				var actions = {};

				body.onResize( function( size ) {
							ApplicationArea.width( size.width );
							ApplicationArea.height( size.height );
							backgroundBox.width( size.width );
							backgroundBox.height( size.height );

							frameSystem.xBounds( 0, size.width );
							frameSystem.yBounds( Menu.MenuHeight, size.height - Menu.MenuHeight * 2 );
						} );
			} );
} )();